package com.fcat.base.http.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * 
 * @author Nan 2015-11
 */
public class HttpClientUtil {
	private static PoolingHttpClientConnectionManager cm;
	private static ConnectionKeepAliveStrategy connectionKeepAliveStrategy;
	private static String EMPTY_STR = "";
	private static String UTF_8 = "UTF-8";
	private static RequestConfig requestConfig;

	private synchronized static void init() {
		if (cm == null) {
			cm = new PoolingHttpClientConnectionManager();
			cm.setMaxTotal(100);// 整个连接池最大连接数
			cm.setDefaultMaxPerRoute(200);// 每路由最大连接数，默认值是2

			connectionKeepAliveStrategy = (response, context) -> {
				HeaderElementIterator it = new BasicHeaderElementIterator
						(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
				while (it.hasNext()) {
					HeaderElement he = it.nextElement();
					String param = he.getName();
					String value = he.getValue();
					if (value != null && param.equalsIgnoreCase
							("timeout")) {
						return Long.parseLong(value) * 1000;
					}
				}
				return 60 * 1000;//如果没有约定，则默认定义时长为60s
			};
			new IdleConnectionMonitorThread(cm).start();
		}
		if(requestConfig==null){
			requestConfig = RequestConfig.custom().setConnectTimeout(1000) //连接超时时间
					.setConnectionRequestTimeout(500) //从线程池中获取线程超时时间
					.setSocketTimeout(1000) //设置数据超时时间
					.build();
		}
	}

	/**
	 * 通过连接池获取HttpClient
	 * 
	 * @return
	 */
	private static CloseableHttpClient getHttpClient() {
		init();
		return HttpClients.custom().setConnectionManager(cm).setKeepAliveStrategy(connectionKeepAliveStrategy).build();
	}

	/**
	 * 
	 * @param url
	 * @return
	 */
	public static String httpGetRequest(String url) {
		HttpGet httpGet = new HttpGet(url);
		return getResult(httpGet);
	}
	/**
	 *
	 * @param url
	 * @return
	 */
	public static String[] httpGetRequestGaode(String url) {
		HttpGet httpGet = new HttpGet(url);
		return getResultGapde(httpGet);
	}
	public static String httpGetRequest(String url, Map<String, Object> params) throws URISyntaxException {
		URIBuilder ub = new URIBuilder();
		ub.setPath(url);

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		ub.setParameters(pairs);

		HttpGet httpGet = new HttpGet(ub.build());
		return getResult(httpGet);
	}

	public static String httpGetRequest(String url, Map<String, Object> headers, Map<String, Object> params)
			throws URISyntaxException {
		URIBuilder ub = new URIBuilder(url);
		//ub.setPath(url);

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		ub.setParameters(pairs);

		HttpGet httpGet = new HttpGet(ub.build());
		for (Map.Entry<String, Object> param : headers.entrySet()) {
			httpGet.addHeader(param.getKey(), String.valueOf(param.getValue()));
		}
		return getResult(httpGet);
	}

	public static String httpPostRequest(String url) {
		HttpPost httpPost = new HttpPost(url);
		return getResult(httpPost);
	}
	public static String httpPostRequest(String url, JSONObject jsonParam) {
		Map<String, Object> headers = new HashMap<>();
		headers.put("Content-Type","application/json");
		headers.put("Content-Encoding","gzip");
		return httpPostRequest(url,headers,jsonParam);
	}

	public static String httpPostRequest(String url, Map<String, Object> headers,JSONObject jsonParam) {
		HttpPost httpPost = new HttpPost(url);
		if(headers!=null){
			for (Map.Entry<String, Object> param : headers.entrySet()) {
				httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
			}
		}
		// json方式
		StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");// 解决中文乱码问题
		entity.setContentEncoding("UTF-8");
		entity.setContentType("application/json");
		httpPost.setEntity(entity);
		return getResult(httpPost);
	}

	public static String httpPostRequest(String url, Map<String, Object> params) throws UnsupportedEncodingException {
		HttpPost httpPost = new HttpPost(url);
		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));
		return getResult(httpPost);
	}

	public static String httpPostRequest(String url, Map<String, Object> headers, Map<String, Object> params)
			throws UnsupportedEncodingException {
		HttpPost httpPost = new HttpPost(url);

		for (Map.Entry<String, Object> param : headers.entrySet()) {
			httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
		}

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));

		return getResult(httpPost);
	}
	public static String httpPostRequestAndSessionId(String url, Map<String, Object> headers, Map<String, Object> params)
			throws UnsupportedEncodingException {
		HttpPost httpPost = new HttpPost(url);

		for (Map.Entry<String, Object> param : headers.entrySet()) {
			httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
		}

		ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
		httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));

		return getResultAndSessionId(httpPost);
	}

	private static ArrayList<NameValuePair> covertParams2NVPS(Map<String, Object> params) {
		ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
		for (Map.Entry<String, Object> param : params.entrySet()) {
			pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue())));
		}

		return pairs;
	}
	/**
	 * 处理Http请求
	 *
	 * @param request
	 * @return
	 */
	private static String[] getResultGapde(HttpRequestBase request) {
		// CloseableHttpClient httpClient = HttpClients.createDefault();
		String[] results = new String[]{EMPTY_STR,EMPTY_STR};
		CloseableHttpClient httpClient = getHttpClient();
		try {
			request.setConfig(requestConfig);
			CloseableHttpResponse response = httpClient.execute(request);
			// response.getStatusLine().getStatusCode();
			Header[] headers = response.getAllHeaders();
			for (Header header:headers){
				if("gsid".equals(header.getName())){
					System.out.println(header.getName()+":"+header.getValue());
					results[0]= header.getValue();
				}
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				// long len = entity.getContentLength();// -1 表示长度未知
				String result = EntityUtils.toString(entity);
				results[1]= result;
				response.close();
				// httpClient.close();
				return results;
				//return xString;
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {

		}

		return results;
	}

	/**
	 * 处理Http请求
	 * 
	 * @param request
	 * @return
	 */
	private static String getResult(HttpRequestBase request) {
		// CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpClient httpClient = getHttpClient();
		try {
			request.setConfig(requestConfig);
			CloseableHttpResponse response = httpClient.execute(request);
			// response.getStatusLine().getStatusCode();
			Header[] headers = response.getAllHeaders();
			for (Header header:headers){
				if("gsid".equals(header.getName())){
					System.out.println(header.getName()+":"+header.getValue());
				}
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				// long len = entity.getContentLength();// -1 表示长度未知
				String result = EntityUtils.toString(entity);
				response.close();
				// httpClient.close();
				return result;
				//return xString;
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {

		}

		return EMPTY_STR;
	}
	
	/**
	 * 处理Http请求
	 * 
	 * @param request
	 * @return
	 */
	private static String getResultAndSessionId(HttpRequestBase request) {
		// CloseableHttpClient httpClient = HttpClients.createDefault();
		CloseableHttpClient httpClient = getHttpClient();
		try {
			CloseableHttpResponse response = httpClient.execute(request);
			// response.getStatusLine().getStatusCode();
			HttpEntity entity = response.getEntity();
			Header headers[]=response.getHeaders("Set-Cookie");
			String sessionId="";
			 for (Header header : headers) {
                 System.err.println(header.getName()+"="+header.getValue());
                 int i=0,j=0;
                 i=header.getValue().indexOf("JSESSIONID=");
                 j=header.getValue().indexOf(";");
                 sessionId=header.getValue().substring(i+11,j);
             }
			System.err.println();
			if (entity != null) {
				// long len = entity.getContentLength();// -1 表示长度未知
				String result = EntityUtils.toString(entity);
				response.close();
				// httpClient.close();
				//return result;
				return sessionId;
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {

		}

		return EMPTY_STR;
	}


	public static  String requstGetUrl(String urlStr,String charset){
		String result = "";
		try {
			URL url = new URL(urlStr);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(5 * 1000);
			if (conn.getResponseCode() == 200) {
				InputStream is = conn.getInputStream();
				BufferedReader reader = new BufferedReader(new InputStreamReader(is, charset));

				StringBuilder sb = new StringBuilder();
				String line;
				while ((line = reader.readLine()) != null) {
					sb.append(line + "\n");
				}
				is.close();
				result = sb.toString();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

}